
package com.scs.application.modules.cert.service.impl;

import cn.afterturn.easypoi.excel.entity.ImportParams;
import cn.afterturn.easypoi.excel.entity.result.ExcelImportResult;
import com.alibaba.fastjson.JSONArray;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.scs.application.consts.GlobalConsts;
import com.scs.application.consts.MsgConsts;
import com.scs.application.core.exceptions.BusinessException;
import com.scs.application.core.global.GlobalDictService;
import com.scs.application.core.msg.domain.SceneMessage;
import com.scs.application.core.msg.enums.MessageType;
import com.scs.application.core.msg.enums.ReceiverType;
import com.scs.application.core.msg.provider.ISceneMsgPushProvider;
import com.scs.application.core.service.BaseServiceImpl;
import com.scs.application.core.utils.*;
import com.scs.application.enums.CertBusType;
import com.scs.application.modules.base.entity.*;
import com.scs.application.modules.base.request.HospitalSupplierRequest;
import com.scs.application.modules.base.service.*;
import com.scs.application.modules.base.vo.HospitalSupplierVO;
import com.scs.application.modules.cert.dto.*;
import com.scs.application.modules.cert.entity.Certificate;
import com.scs.application.modules.cert.entity.CertificateHospitalBusiness;
import com.scs.application.modules.cert.entity.CertificateRepository;
import com.scs.application.modules.cert.entity.CertificateRepositoryHistory;
import com.scs.application.modules.cert.mapper.CertificateHospitalBusinessMapper;
import com.scs.application.modules.cert.mapper.CertificateRepositoryMapper;
import com.scs.application.modules.cert.request.CertificateRepositoryQueryRequest;
import com.scs.application.modules.cert.service.CertificateHospitalBusinessService;
import com.scs.application.modules.cert.service.CertificateRepositoryHistoryService;
import com.scs.application.modules.cert.service.CertificateRepositoryService;
import com.scs.application.modules.cert.service.CertificateService;
import com.scs.application.modules.cert.service.CertMessageService;
import com.google.common.collect.Lists;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.Assert;
import org.springframework.web.multipart.MultipartFile;

import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * 供应商资质仓库 service 实现
 *
 */
@Slf4j
@AllArgsConstructor
@Service
public class CertificateRepositoryServiceImpl extends BaseServiceImpl<CertificateRepositoryMapper, CertificateRepository> implements CertificateRepositoryService {

    private final CertificateRepositoryHistoryService certificateRepositoryHistoryService;

    private final CertificateService certificateService;

    private final CertificateHospitalBusinessService certificateHospitalBusinessService;

    private final CertificateHospitalBusinessMapper certificateHospitalBusinessMapper;

    private final SupplierService supplierService;

    private final ISceneMsgPushProvider sceneMsgPushProvider;

    private final ManufacturerService manufacturerService;

    private final MaterialCatalogService materialCatalogService;

    private final MaterialService materialService;

    private final GlobalDictService globalDictService;

    private final HospitalSupplierService hospitalSupplierService;

    private final HospitalService hospitalService;

    private final HospitalMaterialService hospitalMaterialService;

    private final CertMessageService certMessageService;


    /**
     * 判断资质是否已经上传
     *
     * @param entity
     */
    private void assertCertUnique(CertificateRepository entity) {
        Certificate certificate = certificateService.getById(entity.getCertificateId());


        Assert.notNull(certificate, "资质定义不存在");

        boolean needValidation = true;
        if (StringUtils.isNotBlank(entity.getId())) {
            // 修改之前的信息
            CertificateRepository oldCr = this.getById(entity.getId());

            if (certificate.getId().equals(oldCr.getCertificateId())) {
                needValidation = false;
            }

            // 如果是品类资质
            if (oldCr.getBusinessTypeCode().equals(CertBusType.CATALOG.getValue())) {
                // 判断厂商是否改变
                if (!entity.getManufacturerId().equals(oldCr.getManufacturerId())) {
                    needValidation = true;
                }
            }

            if (!needValidation) {
                return;
            }
        }

        if (certificate.getLimitUnique().shortValue() == GlobalConsts.NO) {
            return;
        }

        //判断所选资质是否限制唯一
        List<CertificateRepository> list = this.list(Wrappers.<CertificateRepository>query()
                .eq("close_flag", CertificateRepository.CLOSE_FLAG_NORMAL)
                .eq("certificate_id", entity.getCertificateId())
                .eq("supplier_id", UserUtils.getSupplierId())
                .eq(StringUtils.isNotBlank(entity.getManufacturerId()), "manufacturer_id", entity.getManufacturerId())
                .eq(StringUtils.isNotBlank(entity.getTargetDescribeId()), "target_describe_id", entity.getTargetDescribeId()));

        //查询该资质是否已经上传

        if (list.size() != 0) {
            throw new BusinessException("所选资质已经上传过，请重新选择");
        }
    }

    @Override
    public List<CertificateRepository> list(CertificateRepositoryQueryRequest request) {
        request.setSupplierId(UserUtils.getSupplierId());
        List<CertificateRepository> list = this.baseMapper.list(request);
        // 获取厂商名称
        List<String> ids = list.stream().map(o -> o.getManufacturerId()).collect(Collectors.toList());
        if (!ids.isEmpty()) {
            Map<String, String> map = manufacturerService.findByIds(ids);
            list.stream().forEach(o -> o.setManufacturerName(map.get(o.getManufacturerId())));
        }
        return list;
    }

    @Override
    public IPage<CertificateRepository> page(CertificateRepositoryQueryRequest request) {
        return this.baseMapper.page(request.getPage(), request);
    }


    /**
     * 获取当前企业资质
     *
     * @param request
     * @return
     */
    @Override
    public IPage<CertificateRepository> pageForSupplier(CertificateRepositoryQueryRequest request) {
        request.setBusinessTypeCode(CertBusType.SUPPLIER.getValue());
        request.setTargetDescribeId(UserUtils.getSupplierId());
        return this.page(request);
    }

    /**
     * 供应商资质效期预警
     *
     * @param request
     * @return
     */
    @Override
    public IPage<CertificateRepository> pageForSupplierWarning(CertificateRepositoryQueryRequest request) {
        request.setSupplierId(UserUtils.getSupplierId());
        return this.baseMapper.pageForSupplierWarning(request.getPage(), request);
    }

    /**
     * 医院资质效期预警
     *
     * @param request
     * @return
     */
    @Override
    public IPage<CertificateRepository> pageForHospitalWarning(CertificateRepositoryQueryRequest request) {
        request.setHospitalId(UserUtils.getHospitalId());
        return this.baseMapper.pageForHospitalWarning(request.getPage(), request);
    }

    /**
     * 供方资格审核，显示供应商资质
     *
     * @param request
     * @return
     */
    @Override
    public List<CertificateRepository> pageForAudit(CertificateRepositoryQueryRequest request) {
        return this.baseMapper.pageForAudit(request);

    }

    /**
     * 添加供应商资质
     *
     * @param entity
     * @return
     */
    @Override
    public boolean saveForSupplier(CertificateRepository entity) {

        //判断资质是否已上传
        this.assertCertUnique(entity);

        entity.setSupplierId(UserUtils.getSupplierId())
                .setSupplierName(UserUtils.getSupplier().getName())
                .setManufacturerId("0")
                .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                .setBusinessTypeCode(CertBusType.SUPPLIER.getValue())
                .setTargetDescribeId(UserUtils.getSupplierId())
                .setVersion(1);

        return this.saveOrUpdate(entity);
    }

    /**
     * 添加品名资质
     *
     * @param entity
     * @return
     */
    @Override
    public boolean saveForMaterial(CertificateRepository entity) {

        //判断资质是否已上传
        this.assertCertUnique(entity);
        Manufacturer manufacturer = manufacturerService.getById(entity.getManufacturerId());

        // 获取末级品类
        Material material = materialService.getById(entity.getTargetDescribeId());
        MaterialCatalog catalog = null;
        if (StringUtils.isNotBlank(material.getCatalogId())) {
            catalog = materialCatalogService.getById(material.getCatalogId());
        }

        // 获取一级品类
        String catalogId = null;
        String catalogName = null;
        if (catalog != null) {
            String[] ids = catalog.getParentIds().split(",");
            String[] names = catalog.getFullName().split("\\\\");
            catalogId = ids.length > 2 ? ids[2] : catalog.getId();
            catalogName = names.length > 1 ? names[0] : catalog.getName();
        }

        entity.setSupplierId(UserUtils.getSupplierId())
                .setSupplierName(UserUtils.getSupplier().getName())
                .setManufacturerName(manufacturer != null ? manufacturer.getName() : null)
                .setCatalogId(catalogId)
                .setCatalogName(catalogName)
                .setMaterialName(material != null ? material.getMaterialName() : null)
                .setBusinessTypeCode(CertBusType.MATERIAL.getValue())
                .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                .setVersion(1);
        return this.saveOrUpdate(entity);
    }

    /**
     * 添加厂商资质
     *
     * @param entity
     * @return
     */
    @Override
    public boolean saveForManufacturer(CertificateRepository entity) {

        //判断资质是否已上传
        this.assertCertUnique(entity);

        Manufacturer manufacturer = manufacturerService.getById(entity.getManufacturerId());

        entity.setSupplierId(UserUtils.getSupplierId())
                .setSupplierName(UserUtils.getSupplier().getName())
                .setManufacturerName(manufacturer != null ? manufacturer.getName() : null)
                .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                .setBusinessTypeCode(CertBusType.MANUFACTURER.getValue())
                .setVersion(1);
        return this.saveOrUpdate(entity);
    }

    /**
     * 添加品类资质
     *
     * @param entity
     * @return
     */
    @Override
    public boolean saveForCatalog(CertificateRepository entity) {

        //判断资质是否已上传
        this.assertCertUnique(entity);
        Manufacturer manufacturer = manufacturerService.getById(entity.getManufacturerId());
        MaterialCatalog catalog = materialCatalogService.getById(entity.getTargetDescribeId());

        entity.setSupplierId(UserUtils.getSupplierId())
                .setSupplierName(UserUtils.getSupplier().getName())
                .setManufacturerName(manufacturer != null ? manufacturer.getName() : null)
                .setCatalogId(catalog != null ? catalog.getId() : null)
                .setCatalogName(catalog != null ? catalog.getName() : null)
                .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                .setVersion(1);
        return this.saveOrUpdate(entity);
    }

    /**
     * 关闭资质，将关闭状态close_flag从 正常状态0 修改为 已关闭状态1
     *
     * @param id
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void close(String id) {
        //关闭
        CertificateRepository cr = this.getById(id);

        if (cr == null) {
            return;
        }

        //当前状态是否正常
        if (cr.getCloseFlag() != CertificateRepository.CLOSE_FLAG_NORMAL) {
            throw new BusinessException("当前状态不是正常状态");
        }

        //修改关闭状态为已关闭 创建对象防止覆盖
        CertificateRepository certificateRepository = new CertificateRepository();
        certificateRepository.setCloseFlag(CertificateRepository.CLOSE_FLAG_CLOSED)
                .setId(cr.getId());
        this.updateById(certificateRepository);

        //保存一条记录到历史表
        CertificateRepositoryHistory crh = new CertificateRepositoryHistory();
        crh.setCertificateRepositoryId(cr.getId())
                .setSupplierId(cr.getSupplierId())
                .setManufacturerId(cr.getManufacturerId())
                .setBusinessTypeCode(cr.getBusinessTypeCode())
                .setTargetDescribeId(cr.getTargetDescribeId())
                .setCertificateId(cr.getCertificateId())
                .setCertificateNo(cr.getCertificateNo())
                .setExpiryDate(cr.getExpiryDate())
                .setCertificateSign(cr.getCertificateSign())
                .setCertificateSignTo(cr.getCertificateSignTo())
                .setDocIds(cr.getDocIds())
                .setVersion(cr.getVersion());

        certificateRepositoryHistoryService.save(crh);

        sendUploadedNotice(cr, true);

    }

    /**
     * 升级资质
     *
     * @param entity
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void upgrade(CertificateRepository entity) {

        CertificateRepository old = this.getById(entity.getId());

        if (old == null) {
            return;
        }

        //当前版本号+1
        entity.setVersion(old.getVersion() + 1);
        this.updateById(entity);

        //保存一条记录到历史表
        CertificateRepositoryHistory crh = new CertificateRepositoryHistory();
        crh
                .setVersion(old.getVersion())
                .setCertificateRepositoryId(old.getId())
                .setSupplierId(old.getSupplierId())
                .setManufacturerId(old.getManufacturerId())
                .setBusinessTypeCode(old.getBusinessTypeCode())
                .setTargetDescribeId(old.getTargetDescribeId())
                .setCertificateId(old.getCertificateId())
                .setCertificateNo(old.getCertificateNo())
                .setExpiryDate(old.getExpiryDate())
                .setCertificateSign(old.getCertificateSign())
                .setCertificateSignTo(old.getCertificateSignTo())
                .setDocIds(old.getDocIds())
        ;

        certificateRepositoryHistoryService.save(crh);

        sendUploadedNotice(old, false);

    }

    /**
     * 提醒资质升级
     *
     * @param dto
     */
    @Override
    public void noticeUpgrade(NoticeUpgradeCertDTO dto) {

        CertificateRepository repository = this.getById(dto.getRepositoryId());

        if (repository == null) {
            throw new BusinessException("数据错误");
        }

        Certificate certificate = certificateService.getById(repository.getCertificateId());

        Supplier supplier = supplierService.getById(repository.getSupplierId());

        Manufacturer manufacturer = manufacturerService.getById(repository.getManufacturerId());

        /**
         * 发送提醒升级通知
         */
        SceneMessage sceneMessage = new SceneMessage();
        /*HashMap<String, Object> params = Maps.newHashMap();
        // 邮件参数
        params.put("business_type", globalDictService.getDictLabel("cert_business_type", repository.getBusinessTypeCode(), "unknown"));
        params.put("cert_name", certificate.getName());
        params.put("supplier_name", supplierVO.getName());
        params.put("send_date", DateUtils.format(new Date(), "yyyy-MM-dd"));*/
        sceneMessage
                .addParam("business_type", globalDictService.getDictLabel("cert_business_type", repository.getBusinessTypeCode(), "unknown"), MessageType.EMAIL)
                .addParam("cert_name", certificate.getName(), MessageType.EMAIL)
                .addParam("supplier_name", supplier.getName(), MessageType.EMAIL)
                .addParam("send_date", DateUtils.format(new Date(), "yyyy-MM-dd"), MessageType.EMAIL);

        String certificateTypeStr = globalDictService.getDictLabel("cert_business_type", repository.getBusinessTypeCode(), "unknown") + "-" + certificate.getName();
        String tmp = "即将到期";
        if (repository.getExpiryDate() != null && repository.getExpiryDate().compareTo(new Date()) < 0) {
            tmp = "已经过期";
        }

        String remark = "";
        String manufacturerName = manufacturer == null ? "" : manufacturer.getName();
        /*switch (dto.getBusinessTypeCode()) {
            case CertBusType.SUPPLIER.getValue():
                remark = "企业名称：" + supplierVO.getName();
                break;
            case CertBusType.MANUFACTURER.getValue():
                remark = "厂商名称：" + manufacturerVO.getName();
                *//*params.put("manufacturer_name", manufacturerVO.getName());*//*
                sceneMessage.addParam("manufacturer_name", manufacturerVO.getName(), MessageType.EMAIL);
                break;
            case CertBusType.CATALOG.getValue():
                CatalogVO catalogVO = catalogService.findById(repository.getTargetDescribeId());
                remark = "厂商名称：" + manufacturerVO.getName() + "\r品类名称：" + catalogVO.getName();
                *//*params.put("manufacturer_name", manufacturerVO.getName());
                params.put("catalog_name", catalogVO.getName());*//*
                sceneMessage.addParam("manufacturer_name", manufacturerVO.getName(), MessageType.EMAIL)
                        .addParam("catalog_name", catalogVO.getName(), MessageType.EMAIL);
                break;
            case CertBusType.MATERIAL.getValue():
                MaterialVO materialVO = materialClient.findById(repository.getTargetDescribeId());
                remark = "厂商名称：" + manufacturerVO.getName() + "\r品名：" + materialVO.getMaterialName();
                *//*params.put("manufacturer_name", manufacturerVO.getName());
                params.put("material_name", materialVO.getMaterialName());*//*
                sceneMessage.addParam("manufacturer_name", manufacturerVO.getName(), MessageType.EMAIL)
                        .addParam("material_name", materialVO.getMaterialName(), MessageType.EMAIL);
                break;
        }*/
        if (CertBusType.SUPPLIER.getValue().equals(dto.getBusinessTypeCode())) {
            remark = "企业名称：" + supplier.getName();

        } else if (CertBusType.MANUFACTURER.getValue().equals(dto.getBusinessTypeCode())) {
            remark = "厂商名称：" + manufacturerName;
            sceneMessage.addParam("manufacturer_name", manufacturerName, MessageType.EMAIL);

        } else if (CertBusType.CATALOG.getValue().equals(dto.getBusinessTypeCode())) {
            MaterialCatalog catalog = materialCatalogService.getById(repository.getTargetDescribeId());
            remark = "厂商名称：" + manufacturerName + "\r品类名称：" + catalog.getName();
            sceneMessage.addParam("manufacturer_name", manufacturerName, MessageType.EMAIL)
                    .addParam("catalog_name", catalog == null ? "" : catalog.getName(), MessageType.EMAIL);

        } else if (CertBusType.MATERIAL.getValue().equals(dto.getBusinessTypeCode())) {
            Material material = materialService.getById(repository.getTargetDescribeId());
            remark = "厂商名称：" + manufacturerName + "\r品名：" + material.getMaterialName();
            sceneMessage.addParam("manufacturer_name", manufacturerName, MessageType.EMAIL)
                    .addParam("material_name", material == null ? "" : material.getMaterialName(), MessageType.EMAIL);
        }

        //微信参数
        /*params.put("first", "您好，您的" + certificateTypeStr + tmp);
        params.put("keyword1", certificateTypeStr);
        params.put("keyword2", repository.getExpiryDate());
        params.put("remark", remark);*/
        sceneMessage.addParam("first", "您好，您的" + certificateTypeStr + tmp, MessageType.WECHAT)
                .addParam("keyword1", certificateTypeStr, MessageType.WECHAT)
                .addParam("keyword2", repository.getExpiryDate(), MessageType.WECHAT)
                .addParam("remark", remark, MessageType.WECHAT);

        sceneMessage.setSceneCode(MsgConsts.SCENE_NOTICE_UPGRADE_CERT).setReceiver(supplier.getLoginKey())
                .setReceiverType(ReceiverType.USER);
        sceneMsgPushProvider.push(sceneMessage);
    }


    /**
     * 提醒资质上传
     *
     * @param dto
     */
    @Override
    public void noticeUpload(NoticeUploadCertDTO dto) {

        Certificate certificate = certificateService.getById(dto.getCertificateId());

        Supplier supplier = supplierService.getById(dto.getSupplierId());

        /**
         * 发送提醒上传通知文件
         */
        /*HashMap<String, Object> params = Maps.newHashMap();
        params.put("business_type", globalDictService.getDictLabel("cert_business_type", dto.getBusinessTypeCode(), "unknown"));
        params.put("supplier_name", supplierVO.getName());
        params.put("cert_name", certificate.getName());
        params.put("send_date", DateUtils.format(new Date(), "yyyy-MM-dd"));*/
        SceneMessage message = new SceneMessage();
        message.addParam("business_type", globalDictService.getDictLabel("cert_business_type", dto.getBusinessTypeCode(), "unknown"), MessageType.EMAIL)
                .addParam("supplier_name", supplier.getName(), MessageType.EMAIL)
                .addParam("cert_name", certificate.getName(), MessageType.EMAIL)
                .addParam("send_date", DateUtils.format(new Date(), "yyyy-MM-dd"), MessageType.EMAIL);

        Manufacturer manufacturer;

        String scene = MsgConsts.SCENE_NOTICE_UPLOAD_CERT;
        /*switch (dto.getBusinessTypeCode()) {
            case CertBusType.SUPPLIER.getValue():
                break;
            case CertBusType.MANUFACTURER.getValue():
                manufacturerVO = manufacturerService.findById(dto.getManufacturerId());
                *//*params.put("manufacturer_name", manufacturerVO.getName());*//*
                message.addParam("manufacturer_name", manufacturerVO.getName(), MessageType.EMAIL);
                break;
            case CertBusType.CATALOG.getValue():
                CatalogVO catalogVO = catalogService.findById(dto.getTargetDescribeId());
                *//*params.put("catalog_name", catalogVO.getName());*//*
                manufacturerVO = manufacturerService.findById(dto.getManufacturerId());
                *//*params.put("manufacturer_name", manufacturerVO.getName());*//*
                message.addParam("catalog_name", catalogVO.getName(), MessageType.EMAIL)
                        .addParam("manufacturer_name", manufacturerVO.getName(), MessageType.EMAIL);
                break;
            case CertBusType.MATERIAL.getValue():
                MaterialVO materialVO = materialClient.findById(dto.getTargetDescribeId());
                *//*params.put("material_name", materialVO.getMaterialName());*//*
                manufacturerVO = manufacturerService.findById(dto.getManufacturerId());
                *//*params.put("manufacturer_name", manufacturerVO.getName());*//*
                message.addParam("material_name", materialVO.getMaterialName(), MessageType.EMAIL)
                        .addParam("manufacturer_name", manufacturerVO.getName(), MessageType.EMAIL);
                break;
        }*/
        if (CertBusType.MANUFACTURER.getValue().equals(dto.getBusinessTypeCode())) {

            manufacturer = manufacturerService.getById(dto.getTargetDescribeId());
            message.addParam("manufacturer_name", manufacturer == null ? "" : manufacturer.getName(), MessageType.EMAIL);

        } else if (CertBusType.CATALOG.getValue().equals(dto.getBusinessTypeCode())) {

            MaterialCatalog catalog = materialCatalogService.getById(dto.getTargetDescribeId());
            manufacturer = manufacturerService.getById(dto.getManufacturerId());
            message.addParam("catalog_name", catalog.getName(), MessageType.EMAIL)
                    .addParam("manufacturer_name", manufacturer == null ? "" : manufacturer.getName(), MessageType.EMAIL);

        } else if (CertBusType.MATERIAL.getValue().equals(dto.getBusinessTypeCode())) {
            Material material = materialService.getById(dto.getTargetDescribeId());
            manufacturer = manufacturerService.getById(dto.getManufacturerId());
            message.addParam("material_name", material.getMaterialName(), MessageType.EMAIL)
                    .addParam("manufacturer_name", manufacturer == null ? "" : manufacturer.getName(), MessageType.EMAIL);
        }
        //微信
        String certificateTypeStr = globalDictService.getDictLabel("cert_business_type", dto.getBusinessTypeCode(), "unknown") + "-" + certificate.getName();
        String tmp = "还未上传，需要上传";
        String remark = "请补充资质材料并提交";

        message.addParam("first", "您好，您的" + certificateTypeStr + tmp, MessageType.WECHAT)
                .addParam("keyword1", supplier.getName(), MessageType.WECHAT)
                .addParam("keyword2", DateUtils.format(new Date(), "yyyy-MM-dd"), MessageType.WECHAT)
                .addParam("keyword3", certificateTypeStr + tmp, MessageType.WECHAT)
                .addParam("remark", remark, MessageType.WECHAT);

        message.setSceneCode(scene).setReceiver(supplier.getLoginKey())
                .setReceiverType(ReceiverType.USER);
        sceneMsgPushProvider.push(message);

    }

    /**
     * 资质提交 提交状态 未提交0 修改为 已提交1
     *
     * @param id
     */
    @Override
    public void certificateSubmit(String id) {

        CertificateRepository certificateRepository = this.getById(id);

        if (certificateRepository == null) {
            throw new BusinessException("数据异常");
        }

        //判断当前状态是否未提交
        if (certificateRepository.getSubmitFlag() != CertificateRepository.SUBMIT_FLAG_UNSUBMIT) {
            throw new BusinessException("当前状态不适合提交");
        }

        //提交状态修改为已提交
        CertificateRepository repository = new CertificateRepository();
        repository.setSubmitFlag(CertificateRepository.SUBMIT_FLAG_SUBMITED)
                .setId(certificateRepository.getId());
        this.updateById(repository);

        sendUploadedNotice(certificateRepository, false);
    }

    @Override
    public int countForHospital() {
        return baseMapper.countForHospital(UserUtils.getHospitalId());
    }

    @Override
    public int countForSupplier() {
        return baseMapper.countForSupplier(UserUtils.getSupplierId());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void correctionCert(String hospitalId) {

        // 修正医院资质要求表
        CertRequirementUpdateDO cru = new CertRequirementUpdateDO();
        cru.setHospitalId(hospitalId);

        certMessageService.certRequirementUpdate(cru);

        // 修正资质汇总表
        List<HospitalSupplierVO> supplierVOS = hospitalSupplierService.listBySupplier(new HospitalSupplierRequest().setHospitalId(hospitalId));
        if (supplierVOS.isEmpty()) {
            return;
        }

        List<CertificateRepository> list = this.list(
                Wrappers.<CertificateRepository>query()
                        .eq("close_flag", "0")
                        .eq("submit_flag", "1")
                        .groupBy("supplier_id,business_type_code,target_describe_id")
                        .select("supplier_id,business_type_code,target_describe_id")
                        .in("supplier_id", supplierVOS.stream().map(o -> o.getSupplierId()).collect(Collectors.toSet()))
        );

        for (CertificateRepository cr : list) {
            CertificateUpdateDO cdo = new CertificateUpdateDO();
            cdo.setCertificateId(cr.getCertificateId())
                    .setBusinessTypeCode(cr.getBusinessTypeCode()).setSupplierId(cr.getSupplierId()).setTargetDescribeId(cr.getTargetDescribeId());
            certMessageService.certUploadedUpdate(cdo);
        }
    }

    /**
     * 发送资质上传通知，更新已上传数量
     *
     * @param cr
     */
    private void sendUploadedNotice(CertificateRepository cr, boolean delete) {
        CertificateUpdateDO cu = new CertificateUpdateDO();
        BeanUtils.copyProperties(cr, cu);
        cu.setDelete(delete);

        certMessageService.certUploadedUpdate(cu);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    protected ExcelImportResult doExcelImport(MultipartFile multipartFile, Map<String, Object> params) throws Exception {
        ImportParams importParams = PoiUtils.getDefaultImportParams();
        long currentTimeMillis = System.currentTimeMillis();
        ExcelImportResult importResult = PoiUtils.importExcelMore(multipartFile.getInputStream(), ExcelCertDTO.class, importParams);
        log.info("文件加载耗时：{}", DateUtils.formatTime(System.currentTimeMillis() - currentTimeMillis));
        List<ExcelCertDTO> dtoList = Lists.newArrayList(importResult.getList());

        //查询出医院信息
        List<String> hospitalNameList = dtoList.parallelStream().map(o -> o.getHospitalName()).distinct().collect(Collectors.toList());
        if (hospitalNameList.isEmpty()) {
            throw new BusinessException("请确认医院名称是否已存在");
        }

        Hospital hospital = hospitalService.getOne(new QueryWrapper<Hospital>().eq("name", hospitalNameList.get(0)));
        if (hospital == null) {
            throw new BusinessException("未找到医院信息，请检查");
        }

        // 查询出供应商信息
        List<String> supplierNameList = dtoList.stream().map(o -> o.getSupplierName()).distinct().collect(Collectors.toList());
        if (supplierNameList.isEmpty()) {
            throw new BusinessException("请确认供应商名称是否已存在");
        }
        List<Supplier> suppliers = supplierService.list();
        List<Supplier> supplierList = suppliers.stream().filter(o -> supplierNameList.contains(o.getName())).collect(Collectors.toList());
        if (supplierList.isEmpty()) {
            throw new BusinessException("未找到供应商信息，请检查");
        }
        Map<String, String> supplierMap = supplierList.stream().collect(Collectors.toMap(o -> o.getName(), o -> o.getId(), (o1, o2) -> o1));

        // 查询出资质信息
        List<Certificate> certList = certificateService.list();
        Map<String, Certificate> certMap = certList.stream().collect(Collectors.toMap(o -> o.getCode(), o -> o, (o1, o2) -> o1));

        // 查询出医院要求上传资质信息
        String hospitalId = hospital.getId();
        List<CertificateHospitalBusiness> certHospitalList = certificateHospitalBusinessService.list(Wrappers.<CertificateHospitalBusiness>query()
                .eq("hospital_id", hospitalId));
        Map<String, CertificateHospitalBusiness> certHospitalMap = certHospitalList.stream()
                .collect(Collectors.toMap(o -> o.getCertificateId(), o -> o, (o1, o2) -> o1));

        // 按供应商分组
        Map<String, List<ExcelCertDTO>> dtoMap = dtoList.stream().collect(Collectors.groupingBy(o -> o.getSupplierName()));

        List<CertificateRepository> list = this.list();
        Map<String, CertificateRepository> map = list.stream()
                .collect(Collectors.toMap(o -> o.getTargetDescribeId() + o.getCertificateId(), o -> o, (o1, o2) -> o1));

        List<CertificateRepository> resultList = Lists.newArrayList();
/*
        DefaultSaveHandler<List<ExcelCertDTO>> saveHandler = new DefaultSaveHandler<List<ExcelCertDTO>>() {
            @Override
            public void doSave(int currentIndex, List<ExcelCertDTO> listentity) throws BusinessException {*/

                for (String supplierName : dtoMap.keySet()) {
                    List<ExcelCertDTO> dtos = dtoMap.get(supplierName);
                    if (dtos.isEmpty()) {
                        throw new BusinessException("请确认资质数据是否已存在");
                    }
                    String supplierId = supplierMap.get(supplierName);
                    if (StringUtils.isBlank(supplierId)) {
                        throw new BusinessException(String.format("未找到供应商%s信息，请检查", supplierName));
                    }

                    /**供应商资质处理*/
                    ExcelCertDTO excelCertDTO = dtos.get(0);
                    // 营业执照
                    if (StringUtils.isNotBlank(excelCertDTO.getSpLicenseNo())) {
                        Certificate certificate = certMap.get("S001");
                        // 校验是否医院要求资质
                        String certificateId = certificate.getId();
                        checkChb(hospitalId, certHospitalMap, certificateId);

                        CertificateRepository cert = new CertificateRepository();
                        cert.setSupplierId(supplierId)
                                .setSupplierName(excelCertDTO.getSupplierName())
                                .setBusinessTypeCode(CertBusType.SUPPLIER.getValue())
                                .setTargetDescribeId(supplierId)
                                .setCertificateId(certificateId)
                                .setCertificateName(certificate.getName())
                                .setCertificateNo(excelCertDTO.getSpLicenseNo())
                                .setExpiryDate(excelCertDTO.getSpLicenseExpiryDate())
                                .setManufacturerId("0")
                                .setSubmitFlag(CertificateRepository.SUBMIT_FLAG_SUBMITED)
                                .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                                .setRemark(excelCertDTO.getRemark())
                                .setDocIds(new JSONArray())
                                .setVersion(1);
                        CertificateRepository cr = map.get(cert.getTargetDescribeId() + cert.getCertificateId());
                        if (cr != null) {
                            cert.setId(cr.getId());
                        }
                        resultList.add(cert);
                    }
                    // 医疗器械经营许可证
                    if (StringUtils.isNotBlank(excelCertDTO.getMedicalNo())) {
                        Certificate certificate = certMap.get("S002");
                        // 校验是否医院要求资质
                        CertificateRepository cert = new CertificateRepository();
                        String certificateId = certificate.getId();
                        checkChb(hospitalId, certHospitalMap, certificateId);

                        cert.setSupplierId(supplierId)
                                .setSupplierName(excelCertDTO.getSupplierName())
                                .setBusinessTypeCode(CertBusType.SUPPLIER.getValue())
                                .setTargetDescribeId(supplierId)
                                .setCertificateId(certificateId)
                                .setCertificateName(certificate.getName())
                                .setCertificateNo(excelCertDTO.getMedicalNo())
                                .setExpiryDate(excelCertDTO.getMedicalExpiryDate())
                                .setManufacturerId("0")
                                .setSubmitFlag(CertificateRepository.SUBMIT_FLAG_SUBMITED)
                                .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                                .setRemark(excelCertDTO.getRemark())
                                .setDocIds(new JSONArray())
                                .setVersion(1);
                        CertificateRepository cr = map.get(cert.getTargetDescribeId() + cert.getCertificateId());
                        if (cr != null) {
                            cert.setId(cr.getId());
                        }
                        resultList.add(cert);
                    }


                    // excel厂商信息
                    List<String> manuNameList = dtos.stream().map(ExcelCertDTO::getManufacturerName).distinct().collect(Collectors.toList());
                    if (manuNameList.isEmpty()) {
                        throw new BusinessException("请确认厂商信息是否存在");
                    }
                    // 系统厂商信息
                    List<Manufacturer> manufacturerList = manufacturerService.list(Wrappers.<Manufacturer>query().eq("supplier_id", supplierId));
                    List<Manufacturer> vos = manufacturerList.stream().filter(o -> manuNameList.contains(o.getName())).collect(Collectors.toList());
                    if (vos.isEmpty()) {
                        throw new BusinessException(String.format("供应商下未找到厂商信息，供应商：%s，请检查", supplierName));
                    }
                    // 厂商名称->系统厂商信息映射关系
                    Map<String, Manufacturer> manufacturerMap = vos.stream().collect(Collectors.toMap(o -> o.getName(), o -> o, (o1, o2) -> o1));
                    // 厂商名称->excel厂商信息映射关系
                    Map<String, ExcelCertDTO> manufacturerDtoMap = dtos.stream().collect(Collectors.toMap(o -> o.getManufacturerName(), o -> o, (o1, o2) -> o1));
                    /** 厂商资质处理 */
                    for (String name : manufacturerDtoMap.keySet()) {
                        ExcelCertDTO dto = manufacturerDtoMap.get(name);
                        Manufacturer manufacturerVO = manufacturerMap.get(name);
                        if (manufacturerVO == null) {
                            throw new BusinessException(String.format("厂商不存在， 厂商：%s，请检查", dto.getManufacturerName()));
                        }
                        // 厂商营业执照
                        if (StringUtils.isNotBlank(dto.getMaLicenseNo())) {
                            // 校验是否医院要求资质
                            Certificate certificate = certMap.get("M001");
                            String certificateId = certificate.getId();
                            checkChb(hospitalId, certHospitalMap, certificateId);

                            CertificateRepository cert = new CertificateRepository();
                            String manufacturerId = manufacturerVO.getId();
                            cert.setSupplierId(supplierId)
                                    .setSupplierName(dto.getSupplierName())
                                    .setBusinessTypeCode(CertBusType.MANUFACTURER.getValue())
                                    .setTargetDescribeId(manufacturerId)
                                    .setCertificateId(certificateId)
                                    .setCertificateName(certificate.getName())
                                    .setCertificateNo(dto.getMaLicenseNo())
                                    .setExpiryDate(dto.getMaLicenseExpiryDate())
                                    .setManufacturerId(manufacturerId)
                                    .setManufacturerName(manufacturerVO.getName())
                                    .setSubmitFlag(CertificateRepository.SUBMIT_FLAG_SUBMITED)
                                    .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                                    .setRemark(dto.getRemark())
                                    .setDocIds(new JSONArray())
                                    .setVersion(1);
                            CertificateRepository cr = map.get(cert.getTargetDescribeId() + cert.getCertificateId());
                            if (cr != null) {
                                cert.setId(cr.getId());
                            }
                            resultList.add(cert);
                        }
                        // 厂商生产经营(许可)证证号
                        if (StringUtils.isNotBlank(dto.getProductNo())) {
                            // 校验是否医院要求资质
                            Certificate certificate = certMap.get("M002");
                            String certificateId = certificate.getId();
                            checkChb(hospitalId, certHospitalMap, certificateId);

                            CertificateRepository cert = new CertificateRepository();
                            String manufacturerId = manufacturerVO.getId();
                            cert.setSupplierId(supplierId)
                                    .setSupplierName(dto.getSupplierName())
                                    .setBusinessTypeCode(CertBusType.MANUFACTURER.getValue())
                                    .setTargetDescribeId(manufacturerId)
                                    .setCertificateId(certificateId)
                                    .setCertificateName(certificate.getName())
                                    .setCertificateNo(dto.getProductNo())
                                    .setExpiryDate(dto.getProductExpiryDate())
                                    .setManufacturerId(manufacturerId)
                                    .setManufacturerName(manufacturerVO.getName())
                                    .setSubmitFlag(CertificateRepository.SUBMIT_FLAG_SUBMITED)
                                    .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                                    .setRemark(excelCertDTO.getRemark())
                                    .setDocIds(new JSONArray())
                                    .setVersion(1);
                            CertificateRepository cr = map.get(cert.getTargetDescribeId() + cert.getCertificateId());
                            if (cr != null) {
                                cert.setId(cr.getId());
                            }
                            resultList.add(cert);
                        }
                    }

                    /** 耗材资质处理 */
                    // excel耗材信息
                    List<String> materialList = dtos.stream().map(o -> o.getMaterialName() + o.getMaterialSpec()).distinct().collect(Collectors.toList());
                    if (materialList.isEmpty()) {
                        throw new BusinessException("请确认耗材信息是否存在");
                    }
                    // 查询系统耗材信息
                    List<HospitalMaterial> hmList = hospitalMaterialService.listByHospital(hospitalId, supplierId);
                    List<HospitalMaterial> hospitalMaterialVOS = hmList.stream()
                            .filter(o -> materialList.contains(o.getMaterialName() + o.getMaterialSpec())).collect(Collectors.toList());
                    if (hospitalMaterialVOS.isEmpty()) {
                        throw new BusinessException("未找到医院耗材信息，请检查");
                    }
                    // 耗材名称+耗材规格->系统耗材信息映射关系
                    Map<String, HospitalMaterial> hmMap = hospitalMaterialVOS.stream()
                            .collect(Collectors.toMap(o -> o.getMaterialName() + o.getMaterialSpec(), o -> o, (o1, o2) -> o1));
                    // 耗材名称+耗材规格->excel耗材信息映射关系
                    Map<String, ExcelCertDTO> materialDtoMap = dtos.stream()
                            .collect(Collectors.toMap(o -> o.getMaterialName() + o.getMaterialSpec(), o -> o, (o1, o2) -> o1));

                    for (String s : materialDtoMap.keySet()) {
                        ExcelCertDTO dto = materialDtoMap.get(s);
                        HospitalMaterial hospitalMaterial = hmMap.get(s);
                        if (hospitalMaterial == null) {
                            throw new BusinessException(String.format("耗材不存在，耗材名称：%s，规格：%s，请检查", dto.getMaterialName(), dto.getMaterialSpec()));
                        }
                        Manufacturer manufacturer = manufacturerMap.get(dto.getManufacturerName());
                        if (manufacturer == null) {
                            throw new BusinessException(String.format("耗材所属厂商不存在，耗材名称：%s，规格：%s， 厂商：%s，请检查",
                                    dto.getMaterialName(), dto.getMaterialSpec(), dto.getManufacturerName()));
                        }
                        // 注册证
                        if (StringUtils.isNotBlank(dto.getRegistrationNo())) {
                            // 校验是否是医院要求资质
                            Certificate certificate = certMap.get("P001");
                            String certificateId = certificate.getId();
                            checkChb(hospitalId, certHospitalMap, certificateId);

                            CertificateRepository cert = new CertificateRepository();
                            String materialId = hospitalMaterial.getMaterialId();
                            dto.getRegistrationExpiryDate();
                            cert.setSupplierId(supplierId)
                                    .setSupplierName(dto.getSupplierName())
                                    .setBusinessTypeCode(CertBusType.MATERIAL.getValue())
                                    .setTargetDescribeId(materialId)
                                    .setMaterialName(dto.getMaterialName())
                                    .setCatalogId(hospitalMaterial.getCatalogId())
                                    .setCertificateId(certificateId)
                                    .setCertificateName(certificate.getName())
                                    .setCertificateNo(dto.getRegistrationNo())
                                    .setExpiryDate(dto.getRegistrationExpiryDate())
                                    .setManufacturerId(manufacturer.getId())
                                    .setSubmitFlag(CertificateRepository.SUBMIT_FLAG_SUBMITED)
                                    .setCloseFlag(CertificateRepository.CLOSE_FLAG_NORMAL)
                                    .setRemark(dto.getRemark())
                                    .setDocIds(new JSONArray())
                                    .setVersion(1);
                            CertificateRepository cr = map.get(cert.getTargetDescribeId() + cert.getCertificateId());
                            if (cr != null) {
                                cert.setId(cr.getId());
                            }
                            resultList.add(cert);
                        }
                    }
                }
        /*    }
        };
        BatchSaveTask<ExcelCertDTO> task = new BatchSaveTask(saveHandler, dtoList);

        this.forkJoinPool.invoke(task);*/

        if (resultList.isEmpty()){
            return null;
        }
        this.saveOrUpdateBatch(resultList);
        log.info("共导入资质数量(含新增和修改)：{}", resultList.size());

        return importResult;
    }

    private void checkChb(String hospitalId, Map<String, CertificateHospitalBusiness> certHospitalMap, String certificateId) {
        CertificateHospitalBusiness business = certHospitalMap.get(certificateId);
        if (business == null){
            CertificateHospitalBusiness chb = new CertificateHospitalBusiness();
            chb.setHospitalId(hospitalId).setCertificateId(certificateId);
            certificateHospitalBusinessMapper.insert(chb);
            certHospitalMap.put(certificateId, chb);
        }
    }

    /**
     * 升级资质
     *
     * @param entity
     */
    @Transactional(rollbackFor = Exception.class)
    @Override
    public void upgradeCert(CertificateRepository entity) {

        CertificateRepository old = this.getById(entity.getId());
        BusinessException.throwErrorIf(old == null, "资质不存在或者已被删除");

        if (entity.getSubmitFlag().equals(CertificateRepository.SUBMIT_FLAG_SUBMITED)) {
            //当前版本号+1
            entity.setVersion(old.getVersion() + 1);
        }

        this.updateById(entity);

        //保存一条记录到历史表
        CertificateRepositoryHistory crh = new CertificateRepositoryHistory();
        crh
                .setVersion(old.getVersion())
                .setCertificateRepositoryId(old.getId())
                .setSupplierId(old.getSupplierId())
                .setManufacturerId(old.getManufacturerId())
                .setBusinessTypeCode(old.getBusinessTypeCode())
                .setTargetDescribeId(old.getTargetDescribeId())
                .setCertificateId(old.getCertificateId())
                .setCertificateNo(old.getCertificateNo())
                .setExpiryDate(old.getExpiryDate())
                .setCertificateSign(old.getCertificateSign())
                .setCertificateSignTo(old.getCertificateSignTo())
                .setDocIds(old.getDocIds())
        ;
        certificateRepositoryHistoryService.save(crh);
    }

    private QueryWrapper<CertificateRepository> getWarnQuery() {
        QueryWrapper<CertificateRepository> queryWrapperCert = Wrappers.<CertificateRepository>query().ne("close_flag",CertificateRepository.CLOSE_FLAG_CLOSED).eq("submit_flag", CertificateRepository.SUBMIT_FLAG_SUBMITED);
        if (!UserUtils.isAdmin()) {
            // 只筛选有供货关系的医院
            if (UserUtils.isSupplier()) {
                queryWrapperCert.eq("supplier_id", UserUtils.getSupplierId());
            } else if (UserUtils.isHospital()){ // 只筛选当前医院有供货关系的供应商
                List<HospitalSupplier> spList = hospitalSupplierService.list(Wrappers.<HospitalSupplier>query().eq("hospital_id", UserUtils.getHospitalId()));
                if (!spList.isEmpty()) {
                    queryWrapperCert.in("supplier_id", spList.stream().map(HospitalSupplier::getSupplierId).distinct().collect(Collectors.toList()));
                }else {
                    queryWrapperCert.eq("supplier_id","0");
                }            }
        }
        return queryWrapperCert;
    }

    /**
     * 资质预警数量
     *
     * @param entity
     */
    @Override
    public int countWarn() {
        Map<String,Object> userParam = new HashMap<>();
        userParam.put("queryType", "warn");
        return this.baseMapper.countWarn(getWarnQuery(), userParam);
    }

    /**
     * 资质预警列表
     */
    @Override
    public List<CertificateRepository> listWarn() {
        Map<String,Object> userParam = new HashMap<>();
        userParam.put("queryType", "warn");
        return this.baseMapper.listWarn(getWarnQuery(), userParam);
    }

    @Override
    public boolean saveOrUpdate(CertificateRepository entity) {
        updateTempIdAndFileRef(entity, "");
        return super.saveOrUpdate(entity);
    }

}
